//Array,function,object,string,number,boolean,symbol原始类型都是对象
let obj = new Object()
//Object.prototype.hasOwnProperty()方法返回一个布尔值，指示对象自身属性中是否具有指定的属性（也就是，是否有指定的键）。
console.log(obj.hasOwnProperty('toString')) //false
//Object.prototype.isPrototypeOf()方法用于测试一个对象是否存在于另一个对象的原型链上。
console.log(obj.isPrototypeOf(obj)) //false
//Object.prototype.propertyIsEnumerable()方法返回一个布尔值，表示指定的属性名是否是当前对象可枚举的自身属性。
console.log(obj.propertyIsEnumerable('toString')) //false
//Object.prototype.toLocaleString()方法返回一个该对象的字符串表示。该方法被用于默认情况下被每个Object对象调用，它不被直接的代码所使用。
console.log(obj.toLocaleString()) //[object Object]
//Object.prototype.toString()方法返回一个表示该对象的字符串。
console.log(obj.toString()) //[object Object]
//Object.prototype.valueOf()方法返回指定对象的原始值。
console.log(obj.valueOf()) //{}
//Object.prototype.__defineGetter__()方法将一个函数绑定到一个对象的指定属性上，当那个属性的值被读取时，你所绑定的函数就会被调用。
Object.prototype.__defineGetter__('toString',function(){
    return 'toString'
})
console.log(obj.toString) //toString
//Object.keys()方法会返回一个由一个给定对象的自身可枚举属性组成的数组，数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。
Object.keys(obj).forEach(key=>{
    console.log(key) //toString
})
//Object.values()方法返回一个给定对象自身的所有可枚举属性值的数组，值的顺序与使用for...in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
Object.values(obj).forEach(value=>{
    console.log(value) //toString
})
//Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组，其排列与使用for...in循环遍历该对象时返回的顺序一致（区别在于 for-in 循环也枚举原型链中的属性）。
Object.entries(obj).forEach(([key,value])=>{
    console.log(key,value) //toString toString
})
//Object.includes()方法用来判断一个数组是否包含一个指定的值，根据情况，如果包含则返回true，否则返回false。
console.log(Object.includes(obj,'toString')) //true
//Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
console.log(Object.assign(obj,{a:1})) //{ a: 1 }
//Object.create()方法创建一个新对象，使用现有的对象来提供新创建的对象的__proto__。
console.log(Object.create(obj)) //{}
//Object.defineProperty()方法会直接在一个对象上定义一个新属性，或者修改一个对象的现有属性， 并返回这个对象。
console.log(Object.defineProperty(obj,'a',{value:1})) //{ a: 1 }
//Object.defineProperties()方法直接在一个对象上定义新的属性或修改现有属性，并返回该对象。
console.log(Object.defineProperties(obj,{b:{value:2}})) //{ b: 2 }
//Object.freeze()方法可以冻结一个对象。一个被冻结的对象再也不能被修改；冻结了一个对象则不能向这个对象添加新的属性，不能删除已有属性，不能修改该对象已有属性的可枚举性、可配置性、可写性，以及不能修改已有属性的值。此外，冻结一个对象后该对象的原型也不能被修改。freeze()返回和传入的参数相同的对象。
console.log(Object.freeze(obj)) //{ b: 2 }，可用于vue中不需要修改的对象
//Object.fromEntries()方法把键值对列表转换为一个对象。
console.log(Object.fromEntries([['a',1],['b',2]])) //{ a: 1, b: 2 }
//Object.getOwnPropertyDescriptor()方法返回指定对象上一个自有属性对应的属性描述符。
console.log(Object.getOwnPropertyDescriptor(obj,'b')) //{ value: 2, writable: true, enumerable: true, configurable: true }
//Object.getOwnPropertyDescriptors()方法用来获取一个对象的所有自身属性的描述符。
console.log(Object.getOwnPropertyDescriptors(obj)) //{ b: { value: 2, writable: true, enumerable: true, configurable: true } }
//Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名（包括不可枚举属性但不包括Symbol值作为名称的属性）组成的数组。
console.log(Object.getOwnPropertyNames(obj)) //[ 'b' ]
//Object.getOwnPropertySymbols()方法返回一个给定对象自身的所有 Symbol 属性的数组。
console.log(Object.getOwnPropertySymbols(obj)) //[]
//Object.getPrototypeOf()方法返回指定对象的原型（内部[[Prototype]]属性的值）。
console.log(Object.getPrototypeOf(obj)) //{}
//Object.is()方法判断两个值是否是相同的值。
console.log(Object.is(obj,obj)) //true
//Object.isExtensible()方法判断一个对象是否是可扩展的（是否可以在它上面添加新的属性）。
console.log(Object.isExtensible(obj)) //true
//Object.isFrozen()方法判断一个对象是否被冻结。
console.log(Object.isFrozen(obj)) //true
//Object.isSealed()方法判断一个对象是否被密封。
console.log(Object.isSealed(obj)) //true
//Object.preventExtensions()方法让一个对象变的不可扩展，也就是永远不能再添加新的属性。
console.log(Object.preventExtensions(obj)) //{ b: 2 }
//Object.seal()方法封闭一个对象，阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。
console.log(Object.seal(obj)) //{ b: 2 }
//Object.setPrototypeOf()方法设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性）到另一个对象或  null。
console.log(Object.setPrototypeOf(obj,{})) //{}
//Proxy对象用于定义基本操作的自定义行为（如属性查找、赋值、枚举、函数调用等）。
let proxy = new Proxy(obj,{
    get(target,key,receiver){
        console.log('get')
        return Reflect.get(target,key,receiver)
    }
})
/**
 * Proxy和defineProperty的区别
 * Proxy可以对整个对象进行拦截，而defineProperty只能对对象的属性进行拦截
 * Proxy返回的是一个新对象，而defineProperty返回的是原对象
 * Proxy可以对数组进行拦截，而defineProperty对数组进行拦截会有问题
 * Proxy可以对Map、Set、Reflect、Promise等进行拦截，而defineProperty不能
 * Proxy可以对整个对象进行拦截，而defineProperty只能对对象的属性进行拦截
 * Proxy返回的是一个新对象，而defineProperty返回的是原对象
 * 
 * 在vue2中使用defineProperty对data中的数据进行拦截来实现响应式，所以每个属性中都要重写get和set方法，
 * 而在vue3中使用Proxy对data中的数据进行拦截来实现响应式，所以只需要重写一次get和set方法
 */